package com.ruoyi.business.service.impl;

import com.ruoyi.business.domain.CarPackageAudit;
import com.ruoyi.business.service.IProcessService;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.engine.HistoryService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.history.HistoricActivityInstance;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Comment;
import org.activiti.engine.task.Task;
import org.activiti.image.ProcessDiagramGenerator;
import org.activiti.image.impl.DefaultProcessDiagramGenerator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.zip.ZipInputStream;

@Service
public class ProcessServiceImpl implements IProcessService {

    @Autowired
    private RepositoryService repositoryService;
    @Autowired
    private RuntimeService runtimeService;
    @Autowired
    private TaskService taskService;
    @Autowired
    private HistoryService historyService;


    @Override
    public Deployment deploy(String filePath) throws FileNotFoundException {
        Deployment deploy = null;
        if (filePath.endsWith("bpmn")) {
            deploy = repositoryService.createDeployment()
                    .addInputStream(filePath, new FileInputStream(filePath))
                    .deploy();
        } else {
            ZipInputStream zipInputStream = new ZipInputStream(new FileInputStream(filePath));
            deploy = repositoryService.createDeployment()
                    .addZipInputStream(zipInputStream)
                    .deploy();
        }
        return deploy;
    }

    @Override
    public ProcessDefinition selectProcessDefinitionByDeploymentId(String deploymentId) {
        return repositoryService.createProcessDefinitionQuery()
                .deploymentId(deploymentId)
                .singleResult();
    }

    @Override
    public InputStream getResourceAsStream(String deploymentId) {
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                .deploymentId(deploymentId)
                .singleResult();
        return repositoryService.getResourceAsStream(deploymentId, processDefinition.getResourceName());
    }

    @Override
    public InputStream getProcessImage(String processDefinitionId, List<String> highLightedActivities, List<String> highLightedFlows) {
        // 获取bpmnModel 主要描述节点 连线信息
        BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);

        ProcessDiagramGenerator generator = new DefaultProcessDiagramGenerator();
        // 第一个参数 bomnModel 第二个 需要高亮的节点集合 第三个 需要高亮连线集合
        InputStream inputStream = generator.generateDiagram(bpmnModel, highLightedActivities, highLightedFlows, "宋体", "宋体", "宋体");
        return inputStream;
    }

    @Override
    public ProcessInstance startProcessInstance(String definitionKey, String businessKey, HashMap<String, Object> variables) {
        return runtimeService.startProcessInstanceByKey(definitionKey, businessKey, variables);
    }

    @Override
    public Task getTaskByProcessInstanceId(String processInstanceId) {
        // 注意是processInstanceId
        return taskService.createTaskQuery().processInstanceId(processInstanceId).singleResult();
    }

    @Override
    public void addCandidateUser(Task currentTask, Long userId) {
        taskService.addCandidateUser(currentTask.getId(), String.valueOf(userId));
    }

    @Override
    public InputStream getProcessImageByInstanceId(String instanceId) {

       /* ProcessInstance processInstance = runtimeService
                .createProcessInstanceQuery()
                .processInstanceId(instanceId)
                .singleResult();*/
        // 获取历史流程实例对象
        HistoricProcessInstance processInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(instanceId).singleResult();
        // 获取bpmnModel 主要描述节点 连线的信息
        BpmnModel bpmnModel = repositoryService.getBpmnModel(processInstance.getProcessDefinitionId());
        // 定义绘制图形对象
        ProcessDiagramGenerator generator = new DefaultProcessDiagramGenerator();
        //判断流程是否已经结束了
        ProcessInstance instance = runtimeService.createProcessInstanceQuery().processInstanceId(instanceId).singleResult();
        List<String> activeActivityIds ;
        if (instance != null) {
            // 流程还没结束
            // 获取目前正在流转节点
            activeActivityIds = runtimeService.getActiveActivityIds(processInstance.getId());
        }else{
            // 流程已经结束了
            activeActivityIds = Collections.EMPTY_LIST;
        }
        // 第一个参数 bomnModel 第二个 需要高亮的节点集合 第三个 需要高亮连线集合
        InputStream inputStream = generator.generateDiagram(bpmnModel, activeActivityIds, Collections.EMPTY_LIST, "宋体", "宋体", "宋体");
        return inputStream;
    }

    @Override
    public void deleteProcessInstance(String instanceId) {
        //执行此方法后未审批的任务 act_ru_task 会被删除，流程历史 act_hi_taskinst 不会被删除，并且流程历史的状态为finished完成
        runtimeService.deleteProcessInstance(instanceId, "撤销申请");
    }


    @Override
    public long selectTodoTaskCount(String definitionKey, String candidateUser) {
        return taskService.createTaskQuery()
                .processDefinitionKey(definitionKey)
                .taskCandidateUser(candidateUser)
                .count();
    }

    @Override
    public List<Task> selectTodoTaskList(String definitionKey, String candidateUser, Integer firstResult, Integer pageSize) {

        return taskService.createTaskQuery()
                .processDefinitionKey(definitionKey)
                .taskCandidateUser(candidateUser)
                .orderByTaskCreateTime()
                .desc()
                .listPage(firstResult, pageSize);
    }

    @Override
    public ProcessInstance getProcessInstanceById(String processInstanceId) {
        return runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
    }

    @Override
    public Task getTaskByTaskId(String taskId) {
        return taskService.createTaskQuery().taskId(taskId).singleResult();
    }

    @Override
    public void claimAndCompleteTask(Task task, String userId, boolean auditStatus, String comment) {
        String taskId = task.getId();
        // 给当前任务添加批注信息
        taskService.addComment(taskId, task.getProcessInstanceId(), comment);
        // 认领任务
        taskService.claim(taskId, userId);
        // 执行任务,把流程变量传入
        // 第一次设置直接加入流程遍历中,第二次如果key名字相同,把流程变量覆盖
        taskService.setVariable(taskId, task.getTaskDefinitionKey(), auditStatus);
        taskService.complete(taskId);
    }

    @Override
    public Task getTaskByInstanceId(String processInstanceId) {
        return taskService.createTaskQuery().processInstanceId(processInstanceId).singleResult();
    }

    @Override
    public void claimAndCompleteTask(Task task, String userId, String comment) {
        // 给当前任务添加批注信息
        taskService.addComment(task.getId(), task.getProcessInstanceId(), comment);
        // 认领任务
        taskService.claim(task.getId(), userId);
        // 执行任务,把流程变量传入
        taskService.complete(task.getId());
    }

    @Override
    public void setVariable(String taskId, String key, long value) {
        taskService.setVariable(taskId, key, value);

        // runtime实际上并没有覆盖流程变量,所以更改价钱后面节点还是没有执行正确的路径
//        runtimeService.setVariable(task.getExecutionId(),key,value);
    }

    @Override
    public long selectDoneTaskCount(String definitionKey, String userId) {
        return historyService
                .createHistoricTaskInstanceQuery()
                .processDefinitionKey(definitionKey)
                .taskAssignee(userId)
                .finished()
                .count();
    }

    @Override
    public List<HistoricTaskInstance> selectDoneTaskList(String definitionKey, String userId, Integer startNum, Integer pageSize) {
        return historyService
                .createHistoricTaskInstanceQuery()
                .processDefinitionKey(definitionKey)
                .taskAssignee(userId)
                .finished()
                .orderByHistoricTaskInstanceEndTime()// 根据任务完成时间来排序
                .desc()
                .listPage(startNum, pageSize);
    }

    @Override
    public HistoricProcessInstance getHistoricProcessInstanceById(String processInstanceId) {
        HistoricProcessInstance historicProcessInstance = historyService
                .createHistoricProcessInstanceQuery()
                .processInstanceId(processInstanceId)
                .singleResult();
        return historicProcessInstance;
    }

    @Override
    public List<HistoricActivityInstance> selectHistoryTaskList(String instanceId) {
        List<HistoricActivityInstance> activityInstanceList = historyService.createHistoricActivityInstanceQuery()
                .processInstanceId(instanceId)
                .activityType("userTask")
                .finished()
                .orderByHistoricActivityInstanceEndTime()
                .desc()
                .list();
        return activityInstanceList;
    }

    @Override
    public String getTaskComment(String taskId) {
        List<Comment> taskComments = taskService.getTaskComments(taskId, "comment");
        if(taskComments!=null && taskComments.size()>0){
            return taskComments.get(0).getFullMessage();
        }else{
            return "";
        }
    }
}
